package com.tsmti.lab.controller.activiti;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializeFilter;
import com.tsmti.activiti.dto.ActUserDto;
import com.tsmti.activiti.dto.ProcessNodeDto;
import com.tsmti.activiti.dto.ProcessTaskDto;
import com.tsmti.activiti.dto.WorkflowInfoDto;
import com.tsmti.activiti.entity.ExtendActFlowBus;
import com.tsmti.activiti.entity.ExtendActModel;
import com.tsmti.activiti.entity.ExtendActNodeSet;
import com.tsmti.activiti.entity.ExtendActTaskLog;
import com.tsmti.activiti.service.*;
import com.tsmti.activiti.utils.ActConstants;
import com.tsmti.core.common.constant.Constants;
import com.tsmti.core.common.controller.BaseController;
import com.tsmti.core.common.model.AjaxJson;
import com.tsmti.core.common.query.annotation.PageableDefaults;
import com.tsmti.core.common.query.data.PageJson;
import com.tsmti.core.common.query.data.PropertyPreFilterable;
import com.tsmti.core.common.query.data.QueryPropertyPreFilter;
import com.tsmti.core.common.query.data.Queryable;
import com.tsmti.core.exception.MyException;
import com.tsmti.core.util.ConvertUtil;
import com.tsmti.core.util.StringUtils;
import com.tsmti.system.entity.User;
import com.tsmti.util.UserUtils;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;
import org.apache.log4j.Logger;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.LinkedCaseInsensitiveMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.Result;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @Package：com.tsmti.lab.controller.activiti
 * @Class：ExtendActDealController
 * @Description： 流程办理相关操作
 * @Author：zcw
 * @Date：Created in 2018/8/17 10:26
 * @Company:
 * @Version：
 * @Modified By:
 *
 */
@Controller
@RequestMapping("act/deal")
public class ExtendActDealController extends BaseController{
    private Logger log = Logger.getLogger(getClass());

    @Autowired
    ExtendActModelerService extendActModelService;

    @Autowired
    ActModelerService actModelerService;

    @Autowired
    ExtendActNodeSetService nodesetService;

    @Autowired
    ExtendActTaskLogService tasklogService;

    @Autowired
    TaskService taskService;

    @Autowired
    ExtendActFlowBusService flowbusService;

    /**
     * 列表
     * @param model
     * @param queryable
     * @param propertyPreFilterable
     * @param request
     * @return
     */
    @RequestMapping("list")
    public String list(Model model,Queryable queryable, PropertyPreFilterable propertyPreFilterable, HttpServletRequest request,
                       HttpServletResponse response){
        long start = System.currentTimeMillis();
        System.out.println(System.currentTimeMillis());
        ExtendActModel actModelEntity = new ExtendActModel();
        model.addAttribute("data",actModelEntity);
        long end = System.currentTimeMillis();
        System.out.println(System.currentTimeMillis());
        System.out.println(end - start);
        return "activiti/extendActModelList";
    }

    /**
     * 根据页码和每页记录数，以及查询条件动态加载数据
     *
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping(value = "ajaxList", method = { RequestMethod.GET, RequestMethod.POST })
    @PageableDefaults(sort = "id=desc")
    public void ajaxList(Queryable queryable, PropertyPreFilterable propertyPreFilterable, HttpServletRequest request,
                         HttpServletResponse response) throws IOException {
        DetachedCriteria detachedCriteria = DetachedCriteria.forClass(ExtendActModel.class);
        detachedCriteria.add(Restrictions.eq("delFlag",0));
        SerializeFilter filter = propertyPreFilterable.constructFilter(ExtendActModel.class);
        PageJson<ExtendActModel> pagejson = new PageJson<ExtendActModel>(extendActModelService.findPage(queryable.getPageable(), detachedCriteria));
        String content = JSON.toJSONString(pagejson, filter);
        StringUtils.printJson(response, content);
    }

    /**
     * 根据流程key 获取业务可用的流程
     * @param model
     * @param actKey
     * @param busId
     * @return
     */
    @RequestMapping("queryFlowsByActKey")
    public String queryFlowsByActKey(Model model, String actKey, String busId){
        List<Map<String,Object>> defs = actModelerService.queryFlowsByActKey(actKey);
        model.addAttribute("defList",defs);
        model.addAttribute("busId",busId);
        model.addAttribute("actKey",actKey);
        return "activiti/flowSubmit.jsp";
    }

    /**
     * 获取当前节点可选择的审批人
     * @param model
     * @param actKey
     * @param busId
     * @return
     */
    @RequestMapping("getUsers")
    public String getUsers(Model model, String actKey, String busId){
        List<Map<String,Object>> defs = actModelerService.queryFlowsByActKey(actKey);
        model.addAttribute("defList",defs);
        model.addAttribute("busId",busId);
        model.addAttribute("actKey",actKey);
        return "activiti/flowSubmit.jsp";
    }

    /**
     * 获取流程第一个节点信息
     * @param deployId 部署id
     * @return
     */
    @RequestMapping(value = "getStartFlowInfo",method = RequestMethod.POST)
    @ResponseBody
    public AjaxJson getStartFlowInfo(String deployId){
        AjaxJson result = null;
        try {
            WorkflowInfoDto workflowInfoDto = actModelerService.getStartFlowInfo(deployId);
            result = AjaxJson.success();
            result.setData(workflowInfoDto);
        } catch (IOException e) {
            e.printStackTrace();
            result = AjaxJson.fail("获取第一个节点信息失败!");
        }
        return result;
    }

    /**
     * 流程选择审批人窗口
     * @param queryable
     * @param propertyPreFilterable
     * @param request
     * @param user
     * @param model
     * @return
     */
    @RequestMapping(value = "userWindow")
    public String userWindow(Queryable queryable, PropertyPreFilterable propertyPreFilterable, HttpServletRequest request, HttpServletResponse response,User user, Model model,String nodeId,String nodeAction){
        DetachedCriteria detachedCriteria = DetachedCriteria.forClass(ExtendActModel.class);
        queryable.addCondition("delFlag", "0");
        SerializeFilter filter = propertyPreFilterable.constructFilter(ExtendActModel.class);
        Map<String,Object> params = new HashMap<>(2);
        params.put("nodeId",nodeId);
        params.put("userName",user.getUserName());
        PageJson<ActUserDto> pagejson = new PageJson<ActUserDto>(actModelerService.userWindowPage(params,queryable));
        String content = JSON.toJSONString(pagejson, filter);
        StringUtils.printJson(response, content);
        return display("activiti/userWindow.jsp");
    }

    /**
     * 转办变更人选择弹框
     * @param user
     * @return
     */
    @RequestMapping(value = "turnUserWindow")
    public String turnUserWindow(Queryable queryable, PropertyPreFilterable propertyPreFilterable,User user, HttpServletRequest request,HttpServletResponse response, Model model){
        DetachedCriteria detachedCriteria = DetachedCriteria.forClass(ExtendActModel.class);
        queryable.addCondition("delFlag", "0");
        Map<String,Object> params = new HashMap<>(2);
        params.put("userName",user.getUserName());
        SerializeFilter filter = propertyPreFilterable.constructFilter(ExtendActModel.class);
        PageJson<ActUserDto> pagejson = new PageJson<ActUserDto>(actModelerService.turnWindowList(params,queryable));
        String content = JSON.toJSONString(pagejson, filter);
        StringUtils.printJson(response, content);
        return display("activiti/userWindow.jsp");
    }

    /**
     * 启动流程
     * @param processTaskDto 完成任务dto
     * @return
     */
    @RequestMapping(value = "startFlow",method = RequestMethod.POST)
    @ResponseBody
    public AjaxJson startFlow(ProcessTaskDto processTaskDto){
        AjaxJson result = null;
        try {
            actModelerService.startFlow(processTaskDto);
            result=AjaxJson.success("提交成功!");
        } catch (Exception e) {
            e.printStackTrace();
            result=AjaxJson.fail("提交失败!");
        }
        return result;
    }

    /**
     * 获取实时流程图
     * @param processInstanceId 流程实例
     * @return
     */
    @RequestMapping(value = "showFlowImg",method = RequestMethod.GET)
    @ResponseBody
    public Result showFlowImg(String processInstanceId, HttpServletResponse response){
        try {
            InputStream inputStream = actModelerService.getFlowImgByInstantId(processInstanceId);
            //输出到页面
            byte[] b = new byte[Constants.READ_NUM];
            int len;
            while ((len = inputStream.read(b, 0, Constants.READ_NUM)) != -1) {
                response.getOutputStream().write(b, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 我的待办列表
     * @param model
     * @param queryable
     * @param response
     * @param request
     * @return
     */
    @RequestMapping("myUpcoming")
    @RequiresPermissions("act:model:myUpcoming")
    public String myUpcoming(Queryable queryable, Model model, HttpServletRequest request,HttpServletResponse response){
        String orgId = ConvertUtil.null2String(request.getParameter("orgId"));
        if(StringUtils.isEmpty(orgId)){
            orgId = UserUtils.getOrgId();
        }
        model.addAttribute("orgId",orgId);
        return "activiti/myUpcoming";
    }

    @RequestMapping("ajaxMyUpcomingList")
    @RequiresPermissions("act:model:myUpcoming")
    public void getMyDoneList(Model model,Queryable queryable, PropertyPreFilterable propertyPreFilterable, HttpServletRequest request,HttpServletResponse response){
        String code = ConvertUtil.null2String(request.getParameter("code"));
        String busId = ConvertUtil.null2String(request.getParameter("busId"));
        Map<String,Object> params = new HashMap<>(2);
        params.put("code",code);
        params.put("busId",busId);
        PageJson<ProcessTaskDto> pagejson = new PageJson<ProcessTaskDto>(actModelerService.findMyUpcomingPage(params, queryable));
        SerializeFilter filter = propertyPreFilterable.constructFilter(ProcessTaskDto.class);
        String content = JSON.toJSONString(pagejson,filter);
        StringUtils.printJson(response, content);
    }
    /**
     * 我的已办列表
     * @param model
     * @param queryable
     * @param request
     * @return
     */
    @RequestMapping("myDoneList")
    @RequiresPermissions("act:model:myUpcoming")
    public String myDoneList(Model model,Queryable queryable,  HttpServletRequest request,HttpServletResponse response){
        return "activiti/myDoneList";
    }

    /**
     * 办理任务Tab
     * @param model
     * @param flag 1为查看审批记录，2为办理任务
     * @param request
     * @return
     */
    @RequestMapping("flowInfoTab")
    public String flowInfoTab(String flag , ProcessTaskDto processTaskDto, Model model, HttpServletRequest request){
        String orgId = ConvertUtil.null2String(request.getParameter("orgId"));
        if(StringUtils.isEmpty(orgId)){
            orgId = UserUtils.getOrgId();
        }

        List<ProcessNodeDto> nextActNodes = actModelerService.getNextActNodes(processTaskDto);

        //可变更字段
        Task task = taskService.createTaskQuery().taskId(processTaskDto.getTaskId()).singleResult();
        //查询可更改字段
        ExtendActNodeSet nodesetEntity = nodesetService.queryByNodeId(task.getTaskDefinitionKey());
        //查询需要作为流程条件判断的字段
        Set<String> nextVarNams = actModelerService.getNextVarNams(task.getTaskDefinitionKey(),processTaskDto.getDefId());
        String[] changFile={};
        if(!StringUtils.isEmpty(nodesetEntity.getChangeFiles())){
            changFile=nodesetEntity.getChangeFiles().split(",");
        }
        model.addAttribute("changeFields",changFile);
        model.addAttribute("nextVarNams",nextVarNams);
        model.addAttribute("nextActNodes",nextActNodes);
        model.addAttribute("nextActNodes",nextActNodes.get(0).getNodeUserList());
        model.addAttribute("orgId",orgId);
        model.addAttribute("flag",flag);
        model.addAttribute("taskDto",processTaskDto);


        return "activiti/flowInfoTab";
    }

    /**
     * 流程信息
     * @param model
     * @param request
     * @return
     */
    @RequestMapping(value = "flowInfoHtml",method = RequestMethod.POST)
    public String flowInfoHtml(Model model, HttpServletRequest request, String busId, String instanceId){
        DetachedCriteria detachedCriteria = DetachedCriteria.forClass(ExtendActTaskLog.class);
        detachedCriteria.add(Restrictions.eq("busId",busId));
        List<ExtendActTaskLog> tasklogEntities = tasklogService.list(detachedCriteria);
        model.addAttribute("taskLogs",tasklogEntities);
        model.addAttribute("instanceId",instanceId);
        return "activiti/taskLogImg";
    }

    /**
     * 办理任务时查询业务可更改的字段和必要的流程相关信息
     * @param processTaskDto
     * @return
     */
    @RequestMapping(value = "getChangeFileds",method = RequestMethod.POST)
    @ResponseBody
    public AjaxJson getChangeFileds(ProcessTaskDto processTaskDto){
        if(StringUtils.isEmpty(processTaskDto.getTaskId())){
            throw new MyException("任务id不能为空");
        }
        if(StringUtils.isEmpty(processTaskDto.getInstanceId())){
            throw new MyException("流程实例id不能为空");
        }
        if(StringUtils.isEmpty(processTaskDto.getDefId())){
            throw new MyException("流程定义id不能为空");
        }
        Task task = taskService.createTaskQuery().taskId(processTaskDto.getTaskId()).singleResult();
        //查询可更改字段
        ExtendActNodeSet nodesetEntity = nodesetService.queryByNodeId(task.getTaskDefinitionKey());
        //查询需要作为流程条件判断的字段
        Set<String> nextVarNams = actModelerService.getNextVarNams(task.getTaskDefinitionKey(),processTaskDto.getDefId());
        String[] changFile={};
        if(!StringUtils.isEmpty(nodesetEntity.getChangeFiles())){
            changFile=nodesetEntity.getChangeFiles().split(",");
        }
        return AjaxJson.success().put("changeFields",changFile).put("vars",nextVarNams);
    }

    /**
     * 办理任务时，获取下一个节点的信息
     * @param processTaskDto
     * @return
     */
    @RequestMapping(value = "getNextActNodes",method = RequestMethod.POST)
    @ResponseBody
    public AjaxJson getNextActNodes(ProcessTaskDto processTaskDto){
        List<ProcessNodeDto> nextActNodes = actModelerService.getNextActNodes(processTaskDto);
        return AjaxJson.success().put("nextActNodes",nextActNodes);
    }

    /**
     * 办理任务时，获取下一个节点操作用户
     * @param processTaskDto
     * @return
     */
    @RequestMapping(value = "getNextActNodeUser",method = RequestMethod.POST)
    @ResponseBody
    public AjaxJson getNextActNodeUser(ProcessTaskDto processTaskDto){
        List<ProcessNodeDto> nextActNodes = actModelerService.getNextActNodes(processTaskDto);
        return AjaxJson.success().put("nextActNodes",nextActNodes);
    }

    /**
     * 转到审批任务选择下一级审批者页面
     * @param processTaskDto
     * @param model
     * @return
     */
    @RequestMapping(value = "toDoActTaskView")
    public String toDoActTaskView(ProcessTaskDto processTaskDto,Model model){
        Task task = taskService.createTaskQuery().taskId(processTaskDto.getTaskId()).singleResult();
        //查询需要作为流程条件判断的字段
        Set<String> nextVarNams = actModelerService.getNextVarNams(task.getTaskDefinitionKey(),processTaskDto.getDefId());
        //查询可更改字段
        ExtendActNodeSet nodesetEntity = nodesetService.queryByNodeId(task.getTaskDefinitionKey());
        //查询流程基本信息
        ExtendActFlowBus flowbus = flowbusService.queryByBusIdInsId(processTaskDto.getInstanceId(), processTaskDto.getBusId());
        model.addAttribute("taskDto",processTaskDto);
        model.addAttribute("nodeSet",nodesetEntity);
        model.addAttribute("flowbus",flowbus);
        return "activiti/doActTask";
    }

    /**
     * 办理任务
     * @param processTaskDto
     * @return
     */
    @RequestMapping(value = "doActTask",method = RequestMethod.POST)
    @ResponseBody
    public AjaxJson doActTask(ProcessTaskDto processTaskDto,HttpServletRequest request){
        AjaxJson result = null;
        try {
            Map<String, String[]> parameterMap = request.getParameterMap();
            Map<String,Object> params = new LinkedCaseInsensitiveMap<>();
            for (String key:parameterMap.keySet()){
                params.put(key,parameterMap.get(key)[0]);
            }
            actModelerService.doActTask(processTaskDto,params);
            result = AjaxJson.success("办理任务成功");
        } catch (Exception e) {
            e.printStackTrace();
            result = AjaxJson.fail("办理任务失败");
        }
        return result;
    }

    /**
     * 驳回到任务发起人，重新编辑提交
     * @param processTaskDto
     * @return
     */
    @RequestMapping(value = "backStartUser",method = RequestMethod.POST)
    @ResponseBody
    public AjaxJson backStartUser(ProcessTaskDto processTaskDto,HttpServletRequest request){
        AjaxJson result = null;
        try {
            Map<String, String[]> parameterMap = request.getParameterMap();
            Map<String,Object> params = new LinkedCaseInsensitiveMap<>();
            for (String key:parameterMap.keySet()){
                params.put(key,parameterMap.get(key)[0]);
            }
            actModelerService.endFailFolw(processTaskDto,params);
            result = AjaxJson.success("驳回到发起人,成功");
        } catch (Exception e) {
            e.printStackTrace();
            result = AjaxJson.fail("驳回到发起人,失败");
        }
        return result;
    }

    /**
     * 转到转办页面
     * @param processTaskDto
     * @param model
     * @return
     */
    @RequestMapping(value = "toTurnToDo")
    public String toTurnToDo(ProcessTaskDto processTaskDto,Model model){
        //查询流程基本信息
        ExtendActFlowBus flowbus = flowbusService.queryByBusIdInsId(processTaskDto.getInstanceId(), processTaskDto.getBusId());
        model.addAttribute("taskDto",processTaskDto);
        model.addAttribute("flowbus",flowbus);
        return "activiti/trunTask.jsp";
    }

    /**
     * 转办
     * @param processTaskDto
     * @return
     */
    @RequestMapping(value = "turnToDo",method = RequestMethod.POST)
    @ResponseBody
    public AjaxJson turnToDo(ProcessTaskDto processTaskDto,String toUserId,HttpServletRequest request){
        AjaxJson result;
        try {
            actModelerService.turnToDo(processTaskDto,toUserId);
            result = AjaxJson.success("转办任务,成功");
        } catch (Exception e) {
            e.printStackTrace();
            result = AjaxJson.fail("转办任务,失败");
        }
        return result;
    }


}
